﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Hn.Database.Contrib;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MSocketCore.Hub;
using MSocketCore.Model;
using SuperSocket;
using SuperSocket.Command;

namespace MSocketCore.MSocket
{
    public class ServerContainer
    {
        private readonly IOptions<MConfig> _config;
        private readonly ILogger<MessageClient> _logger;
        private readonly IServiceProvider _serviceProvider;
        public ServerContainer(IOptions<MConfig> config, ILogger<MessageClient> logger, IServiceProvider serviceProvider)
        {
            _config = config;
            _logger = logger;
            _serviceProvider = serviceProvider;
        }

        private IServer Server;
        private ISessionContainer SessionContainer;

        public  void Start()
        {
            Server = SuperSocketHostBuilder.Create<MyPackage, MyPackageFilter>()
              
                .ConfigureSuperSocket(options =>
                {
                    options.Name = _config.Value.Server.Name;
                    options.Listeners = _config.Value.Server.Listeners;
                    options.ClearIdleSessionInterval = _config.Value.Server.ClearIdleSessionInterval;
                    options.IdleSessionTimeOut = _config.Value.Server.IdleSessionTimeOut;
                    options.ReceiveTimeout = 500;
                    options.SendTimeout = 200;
                })
                //.ConfigureServerOptions((context, configuration) =>
                //{
                //    return configuration.GetSection("Server");
                //})
                .UseHostedService<MyServer<MyPackage>>()
                .UseSession<MySession>()
                .UsePackageDecoder<MyPackageDecoder>()
                .UseCommand(commandOptions =>
                {
                    //commandOptions.AddCommand<AFN01>();
                    // register all commands in one aassembly
                    commandOptions.AddCommandAssembly(typeof(AFN01).GetTypeInfo().Assembly);
                })
                //.UseMiddleware<MyMiddlewareBase>()
                .UseClearIdleSession()
                .UseInProcSessionContainer()
                .ConfigureServices((context, services) =>
                {
                    var client = _serviceProvider.GetService<MessageClient>();
                    services.AddSingleton(client);
                    services.AddSingleton(_config);
                    services.AddAutoMapper(typeof(AutoMapperConfig));
                })
                .ConfigureLogging((hostCtx, loggingBuilder) =>
                {
                    loggingBuilder.ClearProviders();
                    loggingBuilder.AddLog4Net("config/log4net.config");
                })
                .ConfigureAppConfiguration((context, config) =>
                {

                    config.Sources.Clear();
                    var env = context.HostingEnvironment;
                    var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory());
#if DEBUG
                    builder = builder.AddJsonFile($"appsettings.{env}.json", optional: false, reloadOnChange: true);
#else
                    builder.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
#endif
                })
                .BuildAsServer();
            Server.StartAsync();
            SessionContainer = Server.GetSessionContainer();

            DbHelper.Initialization(_config.Value.ConnectString);
        }

        public void Stop()
        {
            Server.StopAsync();
        }

        public void Send()
        {
            var c = SessionContainer.GetSessionCount();
            Console.WriteLine(c);
            foreach (var s in SessionContainer.GetSessions())
            {
                Console.WriteLine(s.SessionID);
                s.SendAsync(new byte[] {0x01});
            }
        }

        public void Send(string sn, byte[] data)
        {
            var sessions = SessionContainer.GetSessions<MySession>(p=> p.Sn == sn);
            foreach (var mySession in sessions)
            {
                ((IAppSession)mySession).SendAsync(data);
            }
        }
    }
}